# ifndef _RPC_MESSAGE_H
# define _RPC_MESSAGE_H

#include <cstdint>
#include <memory>
#include <atomic>
#include <vector>
#include <string>
#include <chrono>

namespace Rpc
{

enum MsgType : uint8_t
{
    Json = 0x01,
    Protobuf = 0x02
};

enum PacketType : uint8_t
{
    Request = 0x01,
    Response = 0x02
};

const uint8_t rpcFlag = '$';


class Message
{
public:
    struct MessageHeader{
        uint8_t flag{rpcFlag};
        uint8_t version_{1};
        PacketType packetType_{Request};
        uint64_t requestId_{0};
        MsgType type_{Json};
        uint32_t len_{0};
    };

public:
    const static int headerLengh = 16;
    Message();
    Message(const MessageHeader header, const char* body, std::size_t len);

    ~Message();

    static std::shared_ptr<Message> createMessage();
    static std::atomic<uint64_t> requestId_;
    static std::shared_ptr<Message> parse(const char* buf, std::size_t len);

    void setRequestId(const uint64_t requestId);
    uint64_t getRequestId() const;

    void setMsg(const std::string);
    void setMsg(const MsgType, const std::string);

    void setPacketType(const PacketType type);
    PacketType getPacketType() const;

    char* data();

    void setTimeOut(const std::chrono::seconds);
    std::chrono::seconds getTimeOut() const;

private:
    MessageHeader header_;
    std::vector<char> data_;
    std::chrono::seconds timeOut_{3};
};

}

#endif //_RPC_MESSAGE_H
